home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / 4_0 / DIZZY / SRC / SIMFILE.C < prev    next >
Text File  |  1991-10-04  |  14KB  |  614 lines

  1. /*
  2. >>    Dizzy 1.0    SimFile.c
  3. >>
  4. >>    A digital circuit simulator & design program for the X Window System
  5. >>
  6. >>    Copyright 1990 Juri Munkki, all rights reserved
  7. >>
  8. >>    Please read the included file called "DizzyDoc" for information on
  9. >>    what your rights are concerning this product.
  10. >>
  11. >>    This file contains all file-handling routines for Dizzy.
  12. */
  13.  
  14. #include "dizzy.h"
  15. #include <stdio.h>
  16.  
  17. #ifndef MACINTOSH
  18. extern    char    CurFileName[];    /*    Used only for Unix, */
  19. extern    char    *DestFileName;    /*    see xstuff.h        */
  20. #endif
  21.  
  22. /*
  23. >>    Given a pointer to the element structure,
  24. >>    a position and a width, this routine fills
  25. >>    out the rectangle parts of the structure by
  26. >>    assuming that it follows a standard format.
  27. */
  28. void    PresetElement(newel,x,y,width)
  29. register    Element *newel;
  30. int         x,y;
  31. int         width;
  32. {
  33.     int     pinheight;
  34.     int     inoff,outoff;
  35.     
  36.     pinheight=newel->Inputs>newel->Outputs ?
  37.                                 newel->Inputs :
  38.                                 newel->Outputs;
  39.  
  40.     inoff=(pinheight-newel->Inputs)*8;
  41.     outoff=(pinheight-newel->Outputs)*8;
  42.  
  43.     newel->Flags=0;
  44.     newel->Body.top=y;
  45.     newel->Body.bottom=y+pinheight*16;
  46.     newel->Body.left=x;
  47.     newel->Body.right=x+width;
  48.     
  49.     newel->InRect.left=x-8;
  50.     newel->InRect.right=x;
  51.     newel->InRect.top=y+inoff;
  52.     newel->InRect.bottom=newel->InRect.top+newel->Inputs*16;
  53.     
  54.     newel->OutRect.left=newel->Body.right;
  55.     newel->OutRect.right=newel->Body.right+13;
  56.     newel->OutRect.top=y+outoff;
  57.     newel->OutRect.bottom=newel->OutRect.top+newel->Outputs*16;
  58. }
  59. /*
  60. >>    Open a file, read in all the available data into the
  61. >>    current header and return. If an error occurs, this
  62. >>    routine just quits. Someone could add better error handling.
  63. */
  64. void    OpenFile(thefile)
  65. FILE    *thefile;
  66. {
  67.                 int             version;
  68.                 long            obtype;
  69.                 int             x,y;
  70.     register    Element         *newel;
  71.  
  72.                 int             ins;
  73.                 long            esize;
  74.                 Input            *InArray;
  75.  
  76.                 int             InputCount,OutputCount;
  77.                 
  78.     InputCount=0;
  79.     OutputCount=0;
  80.  
  81.     if(thefile)
  82.     {    if(fscanf(thefile,"Dizzy %d\n",&version))
  83.         {    do
  84.             {    fread(&obtype,sizeof(char),4,thefile);
  85.                 fscanf(thefile," %d %d ",&x,&y);
  86.                 switch(obtype)
  87.                 {    case ORIG:
  88.                         fscanf(thefile,"\n");
  89.                         CurHeader->XOrig=x;
  90.                         CurHeader->YOrig=y;
  91.                         break;
  92.                     case INPT:
  93.                     case CLOK:
  94.                     case ONE_:
  95.                     case ZERO:
  96.                         newel=SimAllocate(sizeof(Element));
  97.                         newel->Flags=0;
  98.                         newel->Type=obtype;
  99.                         newel->Length=sizeof(Element);
  100.                         newel->Inputs=0;
  101.                         newel->Outputs=1;
  102.                         newel->Out[0].Data=0;
  103.  
  104.                         PresetElement(newel,x,y,16);
  105.  
  106.                         switch(obtype)
  107.                         {    case INPT:
  108.                                 newel->PrivData= ++InputCount;
  109.                                 fscanf(thefile,"%d\n",&newel->Out[0].Data);
  110.                                 break;
  111.                             case CLOK:
  112.                                 fscanf(thefile,"%d\n",&newel->PrivData);
  113.                                 break;
  114.                         }
  115.                         break;
  116.                     case AND_:
  117.                     case NAND:
  118.                     case OR__:
  119.                     case NOR_:
  120.                     case XOR_:
  121.                     case NXOR:                    
  122.                         fscanf(thefile,"%d",&ins);
  123.                         esize=sizeof(Element)+sizeof(Input)*ins;
  124.                         newel=SimAllocate(esize);
  125.                         newel->Flags=0;
  126.                         newel->Type=obtype;
  127.                         newel->Length=esize;
  128.                         newel->Inputs=ins;
  129.                         newel->Outputs=1;
  130.                         PresetElement(newel,x,y,32);
  131.                         InArray=(Input *)&(newel->Out[1]);
  132.                         while(ins--)
  133.                         {    fscanf(thefile," %ldP%d",&(InArray->Chip),&(InArray->Pin));
  134.                             InArray++;
  135.                         }
  136.                         fscanf(thefile,"\n");
  137.                         
  138.                         if(obtype==NAND || obtype==NOR_ || obtype==NXOR)
  139.                         {    newel->Flags |= INVERTED;
  140.                         }
  141.                         break;
  142.                     case RS__:
  143.                     case D___:
  144.                     case JK__:
  145.                         if(obtype==JK__)    ins=3;
  146.                         else                ins=2;
  147.                         
  148.                         esize=sizeof(Element)+sizeof(Output)+sizeof(Input)*ins;
  149.                         newel=SimAllocate(esize);
  150.                         newel->Type=obtype;
  151.                         newel->Flags=0;
  152.                         newel->Length=esize;
  153.                         newel->Inputs=ins;
  154.                         newel->Outputs=2;
  155.                         PresetElement(newel,x,y,32);
  156.                         InArray=(Input *)&(newel->Out[2]);
  157.                         while(ins--)
  158.                         {    fscanf(thefile," %ldP%d",&(InArray->Chip),&(InArray->Pin));
  159.                             InArray++;
  160.                         }
  161.                         fscanf(thefile,"\n");
  162.                         break;
  163.                     case CONN:
  164.                         esize=sizeof(Element)+sizeof(Input);
  165.                         newel=SimAllocate(esize);
  166.                         InitConnector(newel,x,y);
  167.                         InArray=(Input *)&(newel->Out[1]);
  168.                         ins=fscanf(thefile,"%ldP%d\n",&(InArray->Chip),&(InArray->Pin));
  169.                         break;
  170.                     case OUTP:
  171.                     case NOT_:
  172.                         esize=sizeof(Element)+sizeof(Input);
  173.                         newel=SimAllocate(esize);
  174.                         newel->Flags=0;
  175.                         newel->Type=obtype;
  176.                         newel->Length=esize;
  177.                         newel->Inputs=1;
  178.                         newel->Outputs=1;
  179.  
  180.                         InArray=(Input *)&(newel->Out[1]);
  181.                         fscanf(thefile,"%ldP%d\n",&(InArray->Chip),&(InArray->Pin));
  182.                         PresetElement(newel,x,y,16);
  183.                         
  184.                         if(obtype==NOT_)
  185.                         {    newel->Flags |= INVERTED;
  186.                         }
  187.                         else
  188.                         {    newel->PrivData= ++OutputCount;
  189.                         }
  190.                         break;
  191.                     case HEXD:
  192.                         esize=sizeof(Element)-sizeof(Output)+4*sizeof(Input);
  193.                         newel=SimAllocate(esize);
  194.                         newel->Type=obtype;
  195.                         newel->Flags=0;
  196.                         newel->Length=esize;
  197.                         newel->Inputs=4;
  198.                         newel->Outputs=0;
  199.                         newel->PrivData=0;
  200.                         PresetElement(newel,x,y,16);
  201.                         InArray=(Input *)&(newel->Out[0]);
  202.                         for(ins=0;ins<4;ins++)
  203.                         {    fscanf(thefile," %ldP%d",&(InArray->Chip),&(InArray->Pin));
  204.                             InArray++;
  205.                         }
  206.                         fscanf(thefile,"\n");
  207.                         break;
  208.                     case CUST:
  209.                         {    unsigned    char    name[MAXFILENAME];
  210.                                         int     i;
  211.                             
  212.                             fgets((char *)name,MAXFILENAME-1,thefile);
  213.                             i= -1;
  214.                             while(name[++i]!=0)
  215.                             {    if(name[i]<32) name[i]=0;
  216.                             }
  217.                             newel=InsertCustomChip((char *)name,x,y);
  218.                             fscanf(thefile," %d",&ins);
  219.  
  220.                             InArray=(Input *)&(newel->Out[newel->Outputs]);
  221.                             if(ins>newel->Inputs)
  222.                                 i=newel->Inputs;
  223.                             else
  224.                                 i=ins;
  225.                             while(i--)
  226.                             {    fscanf(thefile," %ldP%d",&(InArray->Chip),&(InArray->Pin));
  227.                                 InArray++;
  228.                             }
  229.                             i=ins-newel->Inputs;
  230.                             while(i-->0)
  231.                             {    fscanf(thefile," %*ldP%*d");
  232.                             }
  233.  
  234.                             fscanf(thefile,"\n");
  235.                         }
  236.                     case ENDF:
  237.                         break;
  238.                     default:
  239.                         CurHeader->Last=CurHeader->First;
  240.                         fclose(thefile);
  241.                         return;
  242.                 }
  243.             }    while(obtype!=ENDF && !feof(thefile) && !ferror(thefile));
  244.  
  245.             CurHeader->Last=SimEnd+SimPtr-SimBase;
  246.             AssignNumbers();
  247.             IndexToOffset();
  248.         }
  249.         fclose(thefile);
  250.     }
  251. }
  252. /*
  253. >>    Write the main header to a file. This routines doesn't
  254. >>    report any errors. Here's your chance to make dizzy better!
  255. */
  256. void    WriteFile(filename)
  257. char    *filename;
  258. {
  259.                 FILE            *thefile;
  260.                 int             version;
  261.     register    Element         *newel;
  262.                 int             i;
  263.                 Input            *ip;
  264.                 long            offs;
  265.                 Element         *elem;
  266.  
  267.     thefile=fopen(filename,"w");
  268.     if(thefile)
  269.     {    fprintf(thefile,"Dizzy 1\n");
  270.         fprintf(thefile,"ORIG    %d    %d\n",MainHeader->XOrig,MainHeader->YOrig);
  271.         DatabaseCleanup();
  272.         AssignNumbers();
  273.         OffsetToIndex();
  274.         for(offs=MainHeader->First;offs<MainHeader->Last;offs+=elem->Length)
  275.         {    elem=(Element *)(SimBase+offs);
  276.             ip=(Input *)&elem->Out[elem->Outputs];
  277.             
  278.             fwrite(&elem->Type,sizeof(char),4,thefile);
  279.             if(elem->Type == CONN)
  280.             {    fprintf(thefile,"    %d    %d    ",elem->Body.left+4,elem->Body.top+4);
  281.             }
  282.             else
  283.             {    fprintf(thefile,"    %d    %d    ",elem->Body.left,elem->Body.top);
  284.             }
  285.             switch(elem->Type)        
  286.             {    case INPT:
  287.                     fprintf(thefile,"%d\n",elem->Out[0].Data & NEWVALUE);
  288.                     break;
  289.                 case ONE_:
  290.                 case ZERO:
  291.                     fprintf(thefile,"\n");
  292.                     break;
  293.                 case CLOK:
  294.                     fprintf(thefile,"%d\n",elem->PrivData);
  295.                     break;
  296.                 case AND_:
  297.                 case NAND:
  298.                 case OR__:
  299.                 case NOR_:
  300.                 case XOR_:
  301.                 case NXOR:
  302.                     fprintf(thefile,"%d",elem->Inputs);
  303.                     for(i=0;i<elem->Inputs;i++)
  304.                     {    fprintf(thefile,"    %dP%d",(int)ip->Chip,ip->Pin);
  305.                         ip++;
  306.                     }
  307.                     fprintf(thefile,"\n");
  308.                     break;
  309.                 case RS__:
  310.                 case D___:
  311.                 case JK__:
  312.                 case CONN:
  313.                 case OUTP:
  314.                 case NOT_:
  315.                 case HEXD:
  316.                     for(i=0;i<elem->Inputs;i++)
  317.                     {    fprintf(thefile,"    %dP%d",(int)ip->Chip,ip->Pin);
  318.                         ip++;
  319.                     }
  320.                     fprintf(thefile,"\n");
  321.                     break;
  322.                 case CUST:
  323.                     {    TableHeader *customheader;
  324.                     
  325.                         customheader=(TableHeader *)(elem->Inputs+(Input *)&elem->Out[elem->Outputs]);
  326.                         fprintf(thefile,"%s\n",customheader+1);
  327.                         
  328.                         fprintf(thefile,"            %d",elem->Inputs);
  329.                         for(i=0;i<elem->Inputs;i++)
  330.                         {    fprintf(thefile,"    %dP%d",(int)ip->Chip,ip->Pin);
  331.                             ip++;
  332.                         }
  333.                         fprintf(thefile,"\n");
  334.                     }
  335.                     break;
  336.             }
  337.         }
  338.         IndexToOffset();
  339.         fprintf(thefile,"END.\n");
  340.         fclose(thefile);
  341.     }
  342. }
  343.  
  344. /*
  345. >>    Prompt for a filename and open that file, is user said it's ok.
  346. */
  347. void    PromptOpenFile()
  348. {
  349.     FILE        *thefile;
  350. #ifdef MACINTOSH
  351.     long        thetype;
  352.     Point        thepoint = {80,160};
  353.     char        name[256];
  354.     int         vrefnum;
  355.     
  356.     thetype='TEXT';
  357.     SFGetFile(thepoint,"\p",0L,1,&thetype,0L,&NameOfOpenFile);
  358.     if(NameOfOpenFile.good)
  359.     {
  360.         CurHeader->XOrig=0;
  361.         CurHeader->YOrig=0;
  362.         SimEnd=CurHeader->First;
  363.         CurHeader->Last=CurHeader->First;
  364.  
  365.         FileIsNamed= -1;
  366.         GetVol(name,&vrefnum);
  367.         SetVol(0L,NameOfOpenFile.vRefNum);
  368.         BlockMove(1+NameOfOpenFile.fName,name,NameOfOpenFile.fName[0]);
  369.         name[NameOfOpenFile.fName[0]]=0;
  370.         SetWTitle(MyWind,NameOfOpenFile.fName); 
  371.         thefile=fopen(name,"r");
  372.         OpenFile(thefile);
  373.         SetVol(0L,vrefnum);
  374.         InvalRect(&EditR);
  375.     }
  376. #else
  377.     DestFileName=CurFileName;
  378.     if(DoFileSelection())
  379.     {    CurHeader->XOrig=0;
  380.         CurHeader->YOrig=0;
  381.         SimEnd=CurHeader->First;
  382.         CurHeader->Last=CurHeader->First;
  383.         FileIsNamed= -1;
  384.         thefile=fopen(CurFileName,"r");
  385.         OpenFile(thefile);
  386.         InvalRect(&EditR);
  387.     }
  388. #endif
  389. }
  390. void    SaveFileAs();
  391. /*
  392. >>    Save a file with the name that was previously given
  393. >>    or ask for a name, if none was given.
  394. */
  395. void    SaveFile()
  396. {
  397. #ifdef MACINTOSH
  398.     char        name[256];
  399.     int         vrefnum;
  400. #endif
  401.     
  402.     if(FileIsNamed)
  403.     {
  404. #ifdef    MACINTOSH
  405.         GetVol(name,&vrefnum);
  406.         SetVol(0L,NameOfOpenFile.vRefNum);
  407.         BlockMove(1+NameOfOpenFile.fName,name,NameOfOpenFile.fName[0]);
  408.         name[NameOfOpenFile.fName[0]]=0;
  409.         WriteFile(name);
  410.         SetVol(0L,vrefnum);
  411. #else
  412.         WriteFile(CurFileName);
  413. #endif
  414.     }
  415.     else
  416.     {    SaveFileAs();
  417.     }
  418. }
  419. /*
  420. >>    Ask for a filename and call SaveFile.
  421. */
  422. void    SaveFileAs()
  423. {
  424. #ifdef MACINTOSH
  425.     Point        thepoint = { 80, 160 };
  426.  
  427.     SFPutFile(thepoint,"\p",NameOfOpenFile.fName,0L,&NameOfOpenFile);
  428.     if(NameOfOpenFile.good)
  429.     {    FileIsNamed= -1;
  430.         SetWTitle(MyWind,NameOfOpenFile.fName);
  431.         SaveFile();
  432.     }
  433. #else
  434.     DestFileName=CurFileName;
  435.     if(DoFileSelection())
  436.     {    FileIsNamed= -1;
  437.         SaveFile();
  438.     }
  439. #endif
  440. }
  441. /*
  442. >>    This routine is complicated, but basically it inserts
  443. >>    a new header and circuit data inside a single element
  444. >>    on the current level. You can use it to create subchips
  445. >>    from files.
  446. */
  447. Element *InsertCustomChip(name,x,y)
  448. char    *name;
  449. int     x,y;
  450. {
  451.                 FILE        *thefile;
  452.                 TableHeader *saved;
  453.                 long        SimBaseOffset,CurHeaderOffset,NewelOffset;
  454.                 Ptr         savedbase;
  455.     register    Ptr         source,dest;
  456.                 int         ins,outs;
  457.     register    long        esize,size;
  458.                 int         namelen,i,width;
  459.                 Element     *newel;
  460.                 Input        *InArray;
  461.  
  462. #ifdef    MACINTOSH
  463.     SetPort(MyWind);
  464.     TextFont(geneva);
  465.     TextSize(9);
  466.     TextFace(0);
  467. #endif
  468.  
  469.     /*    First extract the file name from the whole path.    */
  470.     namelen=0;
  471.     while(name[namelen++]);
  472.     for(i=namelen;i>0 && name[i]!='/';i--);
  473.     if(name[i]=='/') i++;
  474.     namelen-=i;
  475.  
  476.     /*    Look for the file with the given path and the current path.            */
  477.     thefile=fopen(name,"r");
  478.     if(!thefile)
  479.     {    name+=i;
  480.         i=0;
  481.         thefile=fopen(name,"r");
  482.     }
  483.     
  484.     width=TextWidth(name,i,namelen-1);
  485.  
  486.     /*    Now save the old pointers as offsets while this routine is active.    */
  487.     SimBaseOffset=SimBase-SimPtr;
  488.     CurHeaderOffset=((Ptr) CurHeader)-SimPtr;
  489.  
  490.     /*    Create a new base pointer.                                            */
  491.     SimBase=SimPtr+SimEnd;
  492.     
  493.     /*    Create a new header here. An element structure will later            */
  494.     /*    be inserted before this header.                                        */
  495.     esize=(namelen+i+sizeof(long)-1) & ~(sizeof(long)-1);    /*    force long-word alignment.    */
  496.     newel=SimAllocate(sizeof(TableHeader)+esize);
  497.     CurHeader=(TableHeader *) newel;
  498.     CurHeader->PathLen=namelen+i;
  499.     CurHeader->First=sizeof(TableHeader)+esize;
  500.     CurHeader->TitleLen=namelen;
  501.     CurHeader->TitleWidth=width;
  502.  
  503.     /*    Copy the whole file name (path).    */
  504.     source=name;
  505.     dest=(Ptr)(CurHeader+1);
  506.     size=CurHeader->PathLen;
  507.     while(size--)
  508.     {    *dest++= *source++;
  509.     }
  510.  
  511.     /*    Read the circuit from the file.        */
  512.     NewelOffset=SimBase-(char *)newel;
  513.     OpenFile(thefile);
  514.     newel=(Element *)(SimBase+NewelOffset);
  515.  
  516.     CurHeader->Last=SimPtr+SimEnd-SimBase;
  517.  
  518.     ins=CountElementType(INPT);        /*    Count input pins.    */
  519.     outs=CountElementType(OUTP);    /*    Count output pins.    */
  520.     
  521.     /*    Now we know how large the element will be.            */
  522.     esize=sizeof(Element)+(outs-1)*sizeof(Output)+ins*sizeof(Input);
  523.  
  524.     /*    Allocate room for the element.                        */
  525.     NewelOffset=SimBase-(char *)newel;
  526.     SimAllocate(esize);
  527.     newel=(Element *)(SimBase+NewelOffset);
  528.  
  529.     /*    Insert the element before the header and the data.    */
  530.     dest=SimPtr+SimEnd;
  531.     source=dest-esize;
  532.     size=CurHeader->Last;
  533.     while(size--)
  534.     {    *--dest= *--source;
  535.     }
  536.     
  537.     esize+=CurHeader->Last;
  538.  
  539.     /*    Set element structure values.        */
  540.     newel->Flags=0;
  541.     newel->Type=CUST;
  542.     newel->Length=esize;
  543.     newel->Inputs=ins;
  544.     newel->Outputs=outs;
  545.     
  546.     PresetElement(newel,x,y,(width+31) & ~31);
  547.  
  548.     /*    Fill in inputs and outputs with default values.    */
  549.     InArray=(Input *)&(newel->Out[outs]);
  550.     while(ins--)
  551.     {    InArray->Chip=0;
  552.         InArray->Pin=0;
  553.         InArray++;
  554.     }
  555.     while(outs--)
  556.     {    newel->Out[outs].Data=0;
  557.     }
  558.     
  559.     /*    Restore previous header pointers from offsets.    */
  560.     SimBase=SimPtr+SimBaseOffset;
  561.     CurHeader=(TableHeader *)(SimPtr+CurHeaderOffset);
  562.  
  563.     /*    Advance pointer of last item in current header.    */
  564.     CurHeader->Last=SimPtr-SimBase+SimEnd;
  565.     return    newel;
  566. }
  567. static    char        CustomFileName[2048];
  568.  
  569. /*
  570. >>    Ask for a file name of a custom chip and add that
  571. >>    to the center of the edit area.
  572. */
  573. void    AddCustomChip()
  574. {
  575.     int         x,y;
  576.     Element     *custel;
  577. #ifdef MACINTOSH
  578.     SFReply     customname;
  579.     int         vrefnum;
  580.     long        thetype='TEXT';
  581.     Point        thepoint={64,64};
  582.     char        name[256];
  583.     
  584.     SFGetFile(thepoint,"\p",0L,1,&thetype,0L,&customname);
  585.     if(customname.good)
  586.     {    GetVol(name,&vrefnum);
  587.         SetVol(0L,customname.vRefNum);
  588.  
  589.         BlockMove(1+customname.fName,name,customname.fName[0]);
  590.         name[customname.fName[0]]=0;
  591.         x=((EditR.right-EditR.left)/2+CurHeader->XOrig) & ~7;
  592.         y=((EditR.bottom-EditR.top)/2+CurHeader->XOrig) & ~7;
  593.         ClipEditArea();
  594.         custel=InsertCustomChip(name,x,y);
  595.         SetTrashRect(&custel->Body);
  596.         InvalTrash();
  597.         RestoreClipping();
  598.  
  599.         SetVol(0L,vrefnum);
  600.     }
  601. #else
  602.     DestFileName=CustomFileName;
  603.     if(DoFileSelection())
  604.     {    x=((EditR.right-EditR.left)/2+CurHeader->XOrig) & ~7;
  605.         y=((EditR.bottom-EditR.top)/2+CurHeader->XOrig) & ~7;
  606.         ClipEditArea();
  607.         custel=InsertCustomChip(CustomFileName,x,y);
  608.         SetTrashRect(&custel->Body);
  609.         InvalTrash();
  610.         RestoreClipping();
  611.     }
  612. #endif
  613. }
  614.